<?php
/*
 AMAZON_ASSOCIATE.PHP by martin $ 2009/10/19 19:27:03
*/
header ("Content-Type: text/html; charset=UTF-8");

if(!function_exists('g_')){
 include_once('owner/ini.inc.php');
 include_once('utils.php');
}

include_once('owner/amazon.ini.php');

$APAAccessKey = !empty($AMAZON_CFG) ? $AMAZON_CFG[0] : ''; // Access Key
$APASecretKey = !empty($AMAZON_CFG) ? $AMAZON_CFG[1] : ''; // Secret Access Key
$associateTag = !empty($AMAZON_CFG) ? $AMAZON_CFG[2] : 'ppblog-22'; // アソシエイトプログラムのID
$genre = !empty($AMAZON_CFG) ? $AMAZON_CFG[4] : 'All';
$baseUrl = 'http://ecs.amazonaws.jp/onca/xml';
$Version = '2009-06-01';                         // APAのバージョン

$words = $nav = $out = NL;
$self = htmlspecialchars($_SERVER['PHP_SELF'], ENT_QUOTES);
$itemPage = g_('ItemPage') != '' ? g_('ItemPage') : 1;

$values = array(
  "All" => 'すべて',
  "Books" => ' 和 書 ',
  "ForeignBooks" => ' 洋 書 ',
  "Electronics" => 'エレクトロニクス',
  "Kitchen" => 'ホーム&amp;キッチン',
  "SportingGoods" => ' スポーツ ',
  "HealthPersonalCare" => ' ヘルス ',
  "Music" => ' 音 楽 ',
  "Classical" => 'クラシック',
  "MusicTracks" => '曲名から調べる',
  "DVD" => ' DVD ',
  "VHS" => ' ビデオ ',
  "Software" => 'ソフトウェア',
  "VideoGames" => ' ゲーム ',
  "Hobbies" => 'ホビー',
  "Toys" => 'おもちゃ',
  "Watches" => ' 時 計 ',
);

if(g_('cmd')=='Search' || (isset($amazonAPIResponse) && $amazonAPIResponse == TRUE)){
 $query = $request = array();
 
 if(isset($amazonAPIResponse) && $amazonAPIResponse){
  $INFO = array(
   '<SalesRank>(.+?)</SalesRank>' => 'ranking',
   '<MediumImage><URL>(.+?)</URL>.*?' => 'url',
   '<MediumImage>.*?<Width.+?>(.+?)</Width>' => 'w',
   '<MediumImage>.*?<Height.+?>(.+?)</Height>' => 'h',
   '<Binding>(.+?)</Binding>' => 'genre',
   '<Artist>(.+?)</Artist>' => 'artist',
   '<Label>(.+?)</Label>' => 'label',
   '<Manufacturer>(.*?)</Manufacturer>' => 'man',
   '<FormattedPrice>(.*?)</FormattedPrice>' => 'price',
   '<Title>(.+?)</Title>' => 'item',
   '<ReleaseDate>(.+?)</ReleaseDate>' => 'date',
   '<CustomerReviews>(.+?)</CustomerReviews>' => 'reviews',
   '<AverageRating>(.+?)</AverageRating>' => 'rate',
   );
  $query['Service'] = 'AWSECommerceService';
  $query['AWSAccessKeyId'] = $APAAccessKey;
  $query['AssociateTag'] = $associateTag;
  $query['Operation'] = 'ItemLookup';
  $query['ItemId'] = $ASIN;
  $query['ResponseGroup'] = 'Medium,Reviews';
  $query['Version'] = $Version;
  $query['Timestamp'] = gmdate('Y-m-d\TH:i:s\Z');
 } else {
  $words = g_('Keywords');
  $genre = g_('SearchIndex');
  $INFO = array(
   '<ASIN>(.+?)</ASIN>' => 'Asin',
   '<DetailPageURL>(.+?)</DetailPageURL>' => 'detail',
   '<SalesRank>(.+?)</SalesRank>' => 'ranking',
   '<SmallImage><URL>(.+?)</URL>.*?' => 'url',
   '<SmallImage>.*?<Width.+?>(.+?)</Width>' => 'w',
   '<SmallImage>.*?<Height.+?>(.+?)</Height>' => 'h',
   '<Binding>(.+?)</Binding>' => 'genre',
   '<Label>(.+?)</Label>' => 'label',
   '<Manufacturer>(.*?)</Manufacturer>' => 'man',
   '<FormattedPrice>(.*?)</FormattedPrice>' => 'price',
   '<Title>(.+?)</Title>' => 'item',
   '<ReleaseDate>(.+?)</ReleaseDate>' => 'date',
   '<AverageRating>(.+?)</AverageRating>' => 'rate',
  );
  
  $query['Service'] = 'AWSECommerceService';
  $query['AWSAccessKeyId'] = $APAAccessKey;
  $query['AssociateTag'] = $associateTag;
  $query['Operation'] = 'ItemSearch';
  $query['SearchIndex'] = $genre;
  $query['Keywords'] = $words;
  $query['ItemPage'] = $itemPage;
  $query['ResponseGroup'] = 'Medium,Images';
  $query['Version'] = $Version;
  $query['Timestamp'] = gmdate('Y-m-d\TH:i:s\Z');
 }

 ksort($query);
 foreach ($query as $key => $val){
  $request[] = str_replace('%7E', '~', rawurlencode($key)).'='.str_replace('%7E', '~', rawurlencode($val));
 }
 $request = implode('&', $request);
 $_GET = "GET\necs.amazonaws.jp\n/onca/xml\n$request";
 $sign = base64_encode(hash_hmac('sha256', $_GET, $APASecretKey, TRUE));
 $request .= '&Signature='.str_replace('%7E', '~', rawurlencode($sign));
 $request = $baseUrl.'?'.$request;
 $response = @file_get_contents($request) or FALSE;
 if(isset($amazonAPIResponse) && $amazonAPIResponse && $response){
  if(!strpos($response, '<Binding>')){
   $response = str_replace('<Item>', '<Item><Binding>'.$values[$genre].'</Binding>', $response);
  }
  return $amazonAPIResponse = $response;
 }
 if(!$response) return;
 $noImg = ROOT_PATH.'Images/notfound-amazon.png';
 $stars_url = 'http://ec1.images-amazon.com/images/G/09/x-locale/common/customer-reviews/';

 $rating = array(
  '0.0' => 'stars-0-0._V45729814_.gif',  '0.5' => 'stars-0-5._V45729814_.gif',
  '1.0' => 'stars-1-0._V45729814_.gif',  '1.5' => 'stars-1-5._V45729814_.gif',
  '2.0' => 'stars-2-0._V45729814_.gif',  '2.5' => 'stars-2-5._V45729814_.gif',
  '3.0' => 'stars-3-0._V45729814_.gif',  '3.5' => 'stars-3-5._V45729814_.gif',
  '4.0' => 'stars-4-0._V45729814_.gif',  '4.5' => 'stars-4-5._V45729814_.gif',
  '5.0' => 'stars-5-0._V45729814_.gif',
 );
 $parts = array(
  '</Request>' => "</Request>\n",
  '</CorrectedQuery>' => "</CorrectedQuery>\n",
  '</TotalResults>'=> "</TotalResults>\n",
  '</TotalPages>'=> "</TotalPages>\n",
 );

 $res = str_replace(array_keys($parts), array_values($parts), $response);
 $r = explode(NL, $res);

 if(strpos($r[0], '<Error')==FALSE && isset($r[1]) && $response != FALSE){
  if(strpos($r[1], 'CorrectedQuery')){ // corrected search
   $TotalResults = $r[2]; $TotalPages = $r[3]; $items = $r[4];
   $words = preg_replace('{^.*?<Keywords>(.+?)</Keywords>.+$}', '$1', $r[1]);
   $out .= '<p class="alert">'.preg_replace('{^.*?<Message>(.+?)</Message>.+$}', '$1', $r[1]).'</p>'.NL;
  } else {
   $TotalResults = $r[1]; $TotalPages = $r[2]; $items = $r[3];
  }
  $TotalResults = intval(preg_replace('{<TotalResults>(\d+?)</TotalResults>}', '$1', $TotalResults));
  $TotalPages = intval(preg_replace('{<TotalPages>(\d+?)</TotalPages>}', '$1', $TotalPages));
  $out .= '<p class="center">全部で '.$TotalResults.' アイテム / '.$TotalPages.' ページ見つかりました.</p>'.NL;
  
  preg_match_all('{<Item>(.+?)</Item>}', $items, $items);

  if(isset($items[1])){
   foreach($items[1] as $item){
    $itemInfo = array();
    foreach ($INFO as $key=>$val){
     $_key = strpos($key, 'Price') ? substr($key, 0, 10) : substr($key, 0, 5);
     if(strpos($item, $_key)===FALSE) continue;
     $itemInfo[$val] =  preg_replace("{^.*?".$key.".*$}i", "$1", $item);
    }
    if(isset($itemInfo['url'])){
     $img = '<img src="'.$itemInfo['url'].'" width="'.$itemInfo['w'].'" height="'.$itemInfo['h'].'" alt="" />'.NL;
    } else {
     $itemInfo['url'] = $noImg;
     $img = '<img src="'.$itemInfo['url'].'" width="93" height="96" alt="" />'.NL;
    }
    if(isset($itemInfo['label'])){
     $label = $itemInfo['label'];
    } elseif (isset($itemInfo['Manufacturer'])){
     $label = $itemInfo['Manufacturer'];
    } elseif (isset($itemInfo['Brand'])){
     $label = $itemInfo['Brand'];
    }elseif (isset($itemInfo['Publisher'])){
     $label = $itemInfo['Publisher'];
    } else $label = ' - ';
    $out .= '<div class="amazon-box">
    <p class="entry"><a href="#" onclick=\'showTags("'.$itemInfo['Asin'].'", "'.$itemInfo['item'].'", "'.$associateTag.'");return false;\'>'.$img.'</a></p>
    <p class="title"><a href="'.$itemInfo['detail'].'">'.$itemInfo['item'].'</a></p>
    <ul class="amazon-info">
     <li> メーカー・販売： '.$label.'</li>
     <li> 定 価： '.(isset($itemInfo['price']) ? $itemInfo['price'] : ' な し ').'</li>
    '.(isset($itemInfo['date']) ? '<li> リリース： '.$itemInfo['date'].'</li>' : '').'
    '.(isset($itemInfo['rate']) ?
     '<li> 評 価： <img src="'.$stars_url.$rating[$itemInfo['rate']].'" width="64" height="12" alt=""/></li>' : '').'
     <li> ジャンル：  '.(isset($itemInfo['genre']) ? $itemInfo['genre'] : $values[$genre]).'</li>
    </ul><hr />
    </div>
    ';
   } #foreach outer
  }
  if($itemPage < $TotalPages){
   $nav .= '<p class="nav">[ '.($itemPage > 1 ? '<a href="'.$self.'?'
        .str_replace('ItemPage='.$itemPage, 'ItemPage='.($itemPage - 1), QUERY).'"> &lt;&lt; 前のページ</a> | ' : '')
        .' <strong>'.$itemPage.'</strong> ページ目 | <a href="'.$self.'?'
        .str_replace('ItemPage='.$itemPage, 'ItemPage='.($itemPage + 1), QUERY).'">次のページ &gt;&gt;</a> ]</p>'.NL;
  }
 } else {
  $out .= '<p class="alert">アマゾンから情報をうまく取得できなかったようです.</p>';
 }
}

if(!function_exists('hash_hmac')){
  /* RFC 2104 HMAC implementation for php.
   source:: http://www.php.net/manual/en/function.mhash.php */
 if(function_exists('mhash')){
  function sha256($data = ''){
   return bin2hex(mhash(MHASH_SHA256, $data));
  }
 } else $out .= '<p class="alert">mhashライブラリーのサポートがないようです。サーバーの管理者にお問い合わせを。</p>';

 function hash_hmac($algo, $key, $data, $raw_output = FALSE){
  $b = 64; // byte length for sha256
  if(strlen($key) > $b){
   $key = pack("H*", $algo($key));
  }
  $key  = str_pad($key, $b, chr(0x00));
  $ipad = str_pad('', $b, chr(0x36)); $ipad ^= $key;
  $opad = str_pad('', $b, chr(0x5c)); $opad ^= $key;
  $hmac = $algo($opad . pack("H*", $algo($ipad . $data)));
  if($raw_output){
   return pack("H*", $hmac);
  } else return $hmac;
 }
}

if(!function_exists('g_')){
 function g_($query, $filter=3){
  if(!isset($_GET[$query])) return '';
  return sanitize_data($_GET[$query], $filter);
 }

 function sanitize_data($input, $filter=3){
  $_FILTER1 = array("\0"=>'', "\t"=>'', "\x00"=>'', '|'=>'&#124;', "`"=>'&#96;', "$"=>'&#36;', ","=>'&#44;', '\\'=>'&yen;');
  $_FILTER2 = array("&"=>'&amp;', "<"=>'&lt;', ">"=>'&gt;', '"'=>'&quot;', "'"=>'&#039;');
  if(is_array($input)){
   $_input = array();
   foreach ($input as $key=>$in) $_input[$key] = sanitize_data($in, $filter);
   $input = $_input;
  } else {
   $input = get_magic_quotes_gpc() ? stripslashes($input) : $input;
   switch ($filter){
    case 3 : $input = mb_str_replace(array_keys($_FILTER2+$_FILTER1), array_values($_FILTER2+$_FILTER1), trim($input)); break;
    case 1 : $input = mb_str_replace(array_keys($_FILTER1), array_values($_FILTER1), trim($input)); break;
    case 2 : $input = mb_str_replace(array_keys($_FILTER2), array_values($_FILTER2), trim($input)); break;
    case 0 : $input = trim($input); break;
   }
  }
  return str_replace(array("\r\n","\r","\n"), '`', $input); # 順序大事
 }

 function mb_str_replace($search, $replace, $target){
  if(is_array($search)){
   if(!is_array($replace)) $replace = array($replace);
   foreach ($search as $i => $needle){
    $rep = isset($replace[$i]) ? $replace[$i] : $replace[0];
    $target = my_str_replace($needle, $rep, $target);
   }
   return $target;
  } else return my_str_replace($search, $replace, $target);
 }

 function my_str_replace($search, $replace, $target, $encoding = 'utf-8'){
  $notArray = !is_array($target) ? TRUE : FALSE;
  $target = $notArray ? array($target) : $target;
  $search_len = mb_strlen($search, $encoding);
  $replace_len = mb_strlen($replace, $encoding);
  foreach ($target as $i => $tar){
   $offset = mb_strpos($tar, $search);
   while ($offset !== FALSE){
    $tar = mb_substr($tar, 0, $offset).$replace.mb_substr($tar, $offset + $search_len);
    $offset = mb_strpos($tar, $search, $offset + $replace_len);
   }
   $target[$i] = $tar;
  }
  return $notArray ? $target[0] : $target;
 }
}

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
<head>
<title>ppBlog-Amazon Product Advertising API</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<script type="text/javascript">
 function showTags(asin, item, tag){
  var msg = ' OKボタンを押しすと生成されたタグがテキストエリアに反映されます。';
  var tags = '<!--AMAZON:' +asin+ '--><a href="http://www.amazon.co.jp/exec/obidos/ASIN/'+asin+'/'+tag+'/ref=nosim/"'
           + ' title="tag:'+tag+'">'+item+'</a><!--/AMAZON:'+asin+'-->';
  if(prompt(msg, tags)){
   parent.ed.value = parent.ed.value + tags;
  }
 }
 function setPage(){ document.getElementById('ItemPage').value = 1;}
</script>
<style type="text/css">
body{
 font-size:13px; background:#fff;
 font-family: 'ヒラギノ角ゴ Pro W3','Hiragino Kaku Gothic Pro','メイリオ',Meiryo,'ＭＳ Ｐゴシック',sans-serif;
}
.center{ text-align:center; width:100%; margin: 3em auto; }
.intro { text-align: left; width: 65%; margin: 2em auto; }
.button {border:1px solid #333;font:600 13px arial;background:#FAD132;height:20px;cursor:pointer;}
.alert { text-align:center; color: crimson; }
img {border:solid 1px #c0c0c0;}
.nav { text-align:center; }
.nav a { text-decoration: none; }
.nav a:hover { text-decoration: underline; color: crimson; }
/* ---------------------[ アマゾンアソシエイト表示設定 ]---------------------*/
.amazon-box { margin: .5em auto; padding: .3em .2em;
 width: auto; max-width: 480px; position: relative; border-bottom: dashed 1px #aaa;
} * html .amazon-box { height: 1%; display: inline; }
.amazon-box p.entry { margin: 10px; float: left; }
.amazon-box p.entry a { border: none; }
.amazon-box p.entry a { border: none; }
.amazon-box ul.amazon-info { list-style: none; border: none; }
.amazon-box .title { padding: 10px 0 0 20px; margin: 0 0 10px 0; font-size: 107%; }
.amazon-box ul.amazon-info li { padding-left: 13px; }
.amazon-box ul.amazon-info li img { border: none; }
.amazon-box .title a:hover{ border-bottom: dotted 1px navy; text-decoration: none; }
.amazon-box hr { clear: both; visibility: hidden; }
.amazon-box a { border-bottom: none; text-decoration: underline; }
.searchResults {}
</style>
</head>
<body>
<div class="center">
 <p class="intro">
 　表示された<strong>アイテムの画像をクリック</strong>すると、ppBlog用のアマゾンタグが表示されますのでコピーして記事に張り付けて下さい。
 </p>
 <form action="<?php echo $self?>" method="GET">
  <input type="text" name="Keywords" id="Keywords" value="<?php echo rawurldecode($words);?>" style="width:150px;" onclick="setPage();" />
  <select name="SearchIndex" id="SearchIndex"><?php echo NL;
 foreach ($values as $name => $value){
  if($genre == '') $genre = 'Music';
  $selected = ($name==$genre) ? ' selected="selected"' : '';
  echo '   <option value="'.$name.'"'.$selected.'>'.$value.'</option>'.NL;
 }
 ?>
  </select>
  <input type="hidden" name="cmd" id="cmd" value="Search"/>
  <input type="hidden" name="ItemPage" id="ItemPage" value="<?php echo $itemPage?>"/>
  <input value="search" type="submit" class="button" title="これで検索" />
 </form>
</div>
<div class="searchResults"><?php echo $nav.$out.$nav?></div>
<p class="center">このエリアを隠すには、もとのアマゾンボタンか、下の「close」ボタンをクリック。</p>
<p class="center">
 <button type="button" title="Amazonアソシエイトを閉じる" onclick='parent.o("#amazon_window").toggle();return false;'>  close  </button>
</p>
</body>
</html>
